﻿// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"
#include "HookApiAd.h"
#include <io.h>
#include "fcntl.h"
#include <stdio.h>

#define PIPE_NAME "\\\\.\\Pipe\\en_key"

BOOL findPvf = false;
const char* pvfName = "Script.pvf";
HANDLE pvfHandle = NULL;
FILE* pvfFile = NULL;

const char* rsaKey = "s";
char* pvfKey = NULL;
ULONG keySize = 0;
BOOL _init = false;

typedef HANDLE(WINAPI* ptrCreateFileW)(LPCWSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE);
typedef BOOL(WINAPI* ptrReadFile)(HANDLE, LPVOID, DWORD, LPDWORD, LPOVERLAPPED);


ptrCreateFileW realCreateFileW = NULL;
ptrReadFile realReadFile = NULL;


BOOL init();

BOOL WINAPI MyReadFile(
    HANDLE hFile,
    LPVOID lpBuffer,
    DWORD nNumberOfBytesToRead,
    LPDWORD lpNumberOfBytesRead,
    LPOVERLAPPED lpOverlapped
);
HANDLE
WINAPI
MyCreateFileW(
    LPCWSTR lpFileName,
    DWORD dwDesiredAccess,
    DWORD dwShareMode,
    LPSECURITY_ATTRIBUTES lpSecurityAttributes,
    DWORD dwCreationDisposition,
    DWORD dwFlagsAndAttributes,
    HANDLE hTemplateFile
);
HookApiAd hookApiAd;
BOOL APIENTRY DllMain(HMODULE hModule,
	DWORD  ul_reason_for_call,
	LPVOID lpReserved
)
{
	int errCode = 0;
	FILE* file;
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
        if(init())
        {
            hookApiAd.Add("Kernel32.dll", "CreateFileW", MyCreateFileW, (void**)&realCreateFileW);
            hookApiAd.Add("Kernel32.dll", "ReadFile", MyReadFile, (void**)&realReadFile);
            hookApiAd.DoHook();
        }
		break;
	case DLL_THREAD_ATTACH:

		break;
	case DLL_THREAD_DETACH:

		break;
	case DLL_PROCESS_DETACH: 
        if (_init)
        {
            if (pvfKey)delete[] pvfKey;
            hookApiAd.DoneHook();
        }
		break;
	}
	return TRUE;
}

BOOL init() 
{
    if (WaitNamedPipe(PIPE_NAME, NMPWAIT_WAIT_FOREVER) == FALSE) {
        return false;
    }
    HANDLE hPipe = CreateFile(PIPE_NAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hPipe == INVALID_HANDLE_VALUE)
    {
        CloseHandle(hPipe);
        return false;
    }

    DWORD ReadNum;
    DWORD TotalNum;
    char buff[256];
	memset(buff, 0, sizeof(buff));
    while (true)
    {
        if (ReadFile(hPipe, buff, 255, &ReadNum, NULL) == FALSE)
        {
            break;
        }
		buff[ReadNum] = 0;
        if (pvfKey == NULL)
        {
            pvfKey = new char[ReadNum];
            memcpy(pvfKey,buff,ReadNum);
        }
        else 
        {
            char* growKey = new char[keySize + ReadNum];
            memcpy(growKey, pvfKey, keySize);
            memcpy(growKey + keySize, buff, ReadNum);
            delete[] pvfKey;
            pvfKey = growKey;
        }
        keySize += ReadNum;
    }
    CloseHandle(hPipe);
    if (pvfKey == NULL)return false;
    return _init = true;
}


HANDLE
WINAPI
MyCreateFileW(
    LPCWSTR lpFileName,
    DWORD dwDesiredAccess,
    DWORD dwShareMode,
    LPSECURITY_ATTRIBUTES lpSecurityAttributes,
    DWORD dwCreationDisposition,
    DWORD dwFlagsAndAttributes,
    HANDLE hTemplateFile
)
{
    HANDLE hHandle = NULL;

    // 执行钩子  
    hHandle = (realCreateFileW)(lpFileName, dwDesiredAccess, dwShareMode,
        lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);

    if (!findPvf)
    {
        char output[MAX_PATH];
        memset(output, 0, sizeof(output));
        sprintf(output, "%ws", lpFileName);
        if (strcmp(output, pvfName) == 0)
        {
            findPvf = true;
            pvfHandle = hHandle;
            int nHandle = _open_osfhandle((long)hHandle, _O_APPEND | _O_RDONLY | _O_TEXT);
            if (nHandle != -1) {
                pvfFile = _fdopen(nHandle, "r+");
            }
        }
    }

    return hHandle;
}

BOOL WINAPI MyReadFile(
    HANDLE hFile,
    LPVOID lpBuffer,
    DWORD nNumberOfBytesToRead,
    LPDWORD lpNumberOfBytesRead,
    LPOVERLAPPED lpOverlapped
)
{
    BOOL result = (realReadFile)(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped);

    if (pvfHandle == hFile && findPvf && pvfHandle != NULL && pvfFile != NULL && _init && pvfKey)
    {
        ULONG seek = ftell(pvfFile);
        const ULONG& readed = *lpNumberOfBytesRead;
        for (ULONG i = 0;i < readed;i++)
        {
            ((char*)lpBuffer)[i] ^= pvfKey[(seek++) % keySize];
        }
    }
    return result;
}
